/*
 *  Copyright 2012 Iurii Dunko, Iana Potochniak.
 * 
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 * 
 *       http://www.apache.org/licenses/LICENSE-2.0
 * 
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *  under the License.
 */

package org.opu.yyminijava.execution;

import java.util.Iterator;
import java.util.List;
import static org.opu.yyminijava.codegeneration.ICode.ISTORE;
import org.opu.yyminijava.codegeneration.Instruction;
import org.opu.yyminijava.codegeneration.Method;

/**
 * Method don't know anything about how it will be executed,
 * so the purpose of this class it execute method.
 * According to it purpose it have method and index of the next instruction.
 *
 * @author Iurii Dunko
 * @author Iana Potochniak
 */
public class ExecutionModule implements Iterator<Instruction>{
    public static final String MAIN = "main";
    private static boolean mainMethodWasApplied = false;

    private Method method;
    private List<Instruction> instructions;
    private int index = 0;
    

    public ExecutionModule(Method method) {
        this.method = method;
        instructions = this.method.getInstructions();

        // If it is main method
        if (!mainMethodWasApplied && MAIN.equals(method.getName())){
            mainMethodWasApplied = true;
            // If main method look like:
            // public static void main(String[] args) {...}
            // Then we must skip first instruction of initialisation input
            // variable.
            if (hasNext() && instructions.get(0).getOperationCode() == ISTORE){
                next();
            }
        }
    }

    public static void reset(){
        mainMethodWasApplied = false;
    }

    @Override
    public final boolean hasNext() {
        return instructions.size() > index;
    }

    @Override
    public final Instruction next() {
        return instructions.get(index ++);
    }

    @Override
    public final void remove() {
        throw new UnsupportedOperationException("Removing is not support");
    }

    public void setIndex(int index) {
        this.index = index;
    }

    public Method getMethod() {
        return method;
    }

    @Override
    public String toString() {
        return method.getName();
    }
}
